﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace Client
{
    public partial class Client : Form
    {
        Thread threadclient;
        private Socket clientConnSocket;
        private Socket clientMsgSocket;
        private byte[] messAge = new byte[1024 * 3];
        private byte[] fileReceBuffer = new byte[1024 * 1024];
        private FileStream fs;
        IPEndPoint endPointTcp;
        IPEndPoint endPointUdp;
        private int count;//剩余包数目
        public Client()
        {
            InitializeComponent();
        }

        private void button_conn_Click(object sender, EventArgs e)
        {
            //this.Close(); 
            try
            {
                //建立TCP连接
                endPointTcp = new IPEndPoint(IPAddress.Parse(textip.Text), Convert.ToInt32(textport.Text));
                clientConnSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientConnSocket.Connect(endPointTcp);

                //建立UDP连接
                endPointUdp = new IPEndPoint(IPAddress.Parse(textip.Text), 4321);
                clientMsgSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                clientMsgSocket.Connect(endPointUdp);


                threadclient = new Thread(Recv);
                threadclient.IsBackground = true;
                threadclient.Start();


            }
            catch
            {
                txtLog.AppendText("连接失败");
            }
        }
        void Recv()
        {
            try
            {
                while (true)
                {

                    byte[] msgTemp = new byte[1024 * 5];
                    int msgLength = clientConnSocket.Receive(msgTemp);
                    byte msgType = msgTemp[0];

                    switch (msgType)
                    {
                        //标示符为g,获取在线用户
                        case 103:
                            {
                                byte[] msg = new byte[msgLength];
                                Array.Copy(msgTemp, 0, msg, 0, msgLength);
                                string temp = Encoding.UTF8.GetString(msg.Skip(1).ToArray());
                                temp = temp.Substring(0, msgLength - 2);
                                txtLog.AppendText("\r\n" + "获取在线用户成功");
                                string[] userlist = temp.Split('#');
                                checkedListBox1.Items.Clear();
                                foreach (string str in userlist)
                                {

                                    checkedListBox1.Items.Add(str);
                                }
                            }
                            break;
                        //标示符为p，群发的消息
                        case 112:
                            {
                                byte[] msg = new byte[msgLength];
                                Array.Copy(msgTemp, 0, msg, 0, msgLength);
                                txtLog.AppendText("\r\n" + Encoding.UTF8.GetString(msg.Skip(1).ToArray()));
                            }
                            break;
                        //标示符为s，定点发的消息
                        case 115:
                            {
                                byte[] msg = new byte[msgLength];
                                Array.Copy(msgTemp, 0, msg, 0, msgLength);
                                txtLog.AppendText("\r\n这是一个私聊消息");
                                txtLog.AppendText("\r\n" + Encoding.UTF8.GetString(msg.Skip(1).ToArray()));
                            }
                            break;
                        //表示符为f,文件传递消息
                        case 102:
                            {
                                byte[] msg = new byte[msgLength];
                                Array.Copy(msgTemp, 0, msg, 0, msgLength);
                                if (msg[1] == '#')
                                {
                                    fs = new FileStream(textBox1.Text, FileMode.Create, FileAccess.Write);
                                    count = msg[2];
                                    txtLog.AppendText("\r\n收到服务器群发文件数据包,还剩" + (Convert.ToInt32(count) - 48) + "个 当前包长度：" + msg.Length.ToString());
                                    count--;
                                }
                                else
                                {
                                    txtLog.AppendText("\r\n收到服务器群发文件数据包,还剩" + (Convert.ToInt32(count) - 48) + "个 当前包长度：" + msg.Length.ToString());
                                    if (count > 48)
                                    {
                                        fs.Write(msg, 2, msg.Length - 2);
                                        count--;
                                    }
                                    else
                                    {
                                        fs.Write(msg, 2, msg.Length - 2);
                                        fs.Close();
                                        txtLog.AppendText("\r\n文件接收完成");

                                    }

                                }

                            }
                            break;
                        //表示符为i,文件传递消息 定向发送
                        case 105:
                            {
                                byte[] msg = new byte[msgLength];
                                Array.Copy(msgTemp, 0, msg, 0, msgLength);
                                if (msg[1] == '#')
                                {
                                    fs.Close();
                                    fs = new FileStream(textBox1.Text, FileMode.Create, FileAccess.Write);
                                    count = msg[2];
                                    txtLog.AppendText("\r\n收到服务器定向发送文件数据包,还剩" + (Convert.ToInt32(count) - 48) + "个 当前包长度：" + msg.Length.ToString());
                                    count--;
                                }
                                else
                                {
                                    txtLog.AppendText("\r\n收到服务器定向发送文件数据包,还剩" + (Convert.ToInt32(count) - 48) + "个 当前包长度：" + msg.Length.ToString());
                                    if (count > 48)
                                    {
                                        fs.Write(msg, 2, msg.Length - 2);
                                        count--;
                                    }
                                    else
                                    {
                                        fs.Write(msg, 2, msg.Length - 2);
                                        fs.Close();
                                        txtLog.AppendText("\r\n文件接收完成");

                                    }

                                }

                            }
                            break;
                        //不明白的标示符
                        default:
                            {
                                byte[] msg = new byte[msgLength];
                                Array.Copy(msgTemp, 0, msg, 0, msgLength);
                                txtLog.AppendText("\r\n" + Encoding.UTF8.GetString(msg.Skip(1).ToArray()));
                            }
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

        }

        private void checkedListBox1_SelectedIndexChanged_1(object sender, EventArgs e)
        {

        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        //群发
        private void button_send_Click(object sender, EventArgs e)
        {
            //群发文本 标志字为p 112
            messAge = Encoding.UTF8.GetBytes("p" + textBox3.Text);
            clientConnSocket.Send(messAge);
        }

        //发给指定用户
        private void button1_Click(object sender, EventArgs e)
        {

            //发送文本 标志字段为s 115
            string sendList = "";
            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
                if (checkedListBox1.GetItemChecked(i))
                {
                    sendList += checkedListBox1.Items[i].ToString();
                    sendList += "#";
                }
            }
            byte[] msg = Encoding.UTF8.GetBytes("s" + sendList + textBox3.Text);
            clientConnSocket.Send(msg);

        }

        //获取在线用户列表,标志字段为103，
        private void button2_Click(object sender, EventArgs e)
        {
            messAge = Encoding.UTF8.GetBytes("g########################");
            clientConnSocket.Send(messAge);

        }

        private void textip_TextChanged(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {

        }

        private void txtLog_TextChanged(object sender, EventArgs e)
        {

        }

        private void textport_TextChanged(object sender, EventArgs e)
        {

        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            txtLog.Clear();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            clientConnSocket.Close();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            organizeFile("f", textBox1.Text, "");
            //群发文件，标志字段为f 102
            //FileStream fs = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read);
            //txtLog.AppendText(fs.Name);
            //byte[] fileByte = new byte[(int)fs.Length];
            //fs.Read(fileByte, 0, fileByte.Length);
            ////告诉服务器有多少个包 f#包个数
            //clientConnSocket.Send(Encoding.UTF8.GetBytes("f#" + (fileByte.Length / 5000 + 1) + "#" + textBox1.Text));
            //int i;
            //byte[] fileBuffer = new byte[5002];
            //byte[] temp;
            //for (i = 0; i < fileByte.Length / 5000; i++)
            //{
            //    temp = Encoding.UTF8.GetBytes("f" + i.ToString());
            //    fileBuffer[0] = temp[0];
            //    fileBuffer[1] = temp[1];
            //    Array.Copy(fileByte, i * 5000, fileBuffer, 2, 5000);
            //    txtLog.AppendText("\r\n" + Encoding.UTF8.GetString(fileBuffer) + i);
            //    clientConnSocket.Send(fileBuffer);
            //}
            ////发送最后一个数据包
            //temp = Encoding.UTF8.GetBytes("f" + (i).ToString());
            //fileBuffer = new byte[(fileByte.Length - i * 5000) + 2];
            //fileBuffer[0] = temp[0];
            //fileBuffer[1] = temp[1];
            //Buffer.BlockCopy(fileByte, i * 5000, fileBuffer, 2, fileByte.Length - i * 5000);
            //clientConnSocket.Send(fileBuffer);
            //txtLog.AppendText("\r\n" + "发送成功");
        }

        private void button6_Click(object sender, EventArgs e)
        {
            //私发文件 标志字为i 105
            string sendList = "";
            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
                if (checkedListBox1.GetItemChecked(i))
                {
                    sendList += checkedListBox1.Items[i].ToString();
                    sendList += "#";
                }
            }
            organizeFile("i", textBox1.Text, sendList);

        }
        private void organizeFile(string type, string filePath, string receiver)
        {

            //群发文件，标志字段为f 102
            //私发文件，标志字段为i 105
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            txtLog.AppendText("\r\n开始发送文件:"+fs.Name);
            byte[] fileByte = new byte[(int)fs.Length];
            fs.Read(fileByte, 0, fileByte.Length);
            //告诉服务器有多少个包 f#包个数
            clientConnSocket.Send(Encoding.UTF8.GetBytes(type + "#" + (fileByte.Length / 5118 + 1) + "#" + filePath + "#" + receiver));
            txtLog.AppendText("\r\n发给服务器数据长度"+ Encoding.UTF8.GetBytes(type + "#" + (fileByte.Length / 5118 + 1) + "#" + filePath + "#" + receiver).Length);
            int i;
            byte[] fileBuffer = new byte[5120];
            byte[] temp;
            for (i = 0; i < fileByte.Length / 5118; i++)
            {
                temp = Encoding.UTF8.GetBytes(type + i.ToString());
                fileBuffer[0] = temp[0];
                fileBuffer[1] = temp[1];
                Array.Copy(fileByte, i * 5118, fileBuffer, 2, 5118);
                txtLog.AppendText("\r\n发给服务器数据包:"+i+" 长度："+fileBuffer.Length);
                clientConnSocket.Send(fileBuffer);
            }
            //发送最后一个数据包
            temp = Encoding.UTF8.GetBytes(type + (i).ToString());
            fileBuffer = new byte[(fileByte.Length - i * 5118) + 2];
            fileBuffer[0] = temp[0];
            fileBuffer[1] = temp[1];
            Buffer.BlockCopy(fileByte, i * 5118, fileBuffer, 2, fileByte.Length - i * 5118);
            clientConnSocket.Send(fileBuffer);
            txtLog.AppendText("\r\n发给服务器数据包:" + i + " 长度：" + fileBuffer.Length);
            txtLog.AppendText("\r\n文件发送成功");
            fs.Close();

        }

        private void Client_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }
    }
}
